﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using Ling.P2P.Provider;
using Ling.P2P.DemoLib;

namespace Ling.P2P.PClient
{
    public partial class ClientLogInDlg : Form
    {
        private bool _IsLogIn = false;
        private string ClientName;

        public ClientLogInDlg()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 获取是否登入成功。
        /// </summary>
        public bool IsLogIn
        {
            get { return _IsLogIn; }
        }

        /// <summary>
        /// 登入消息的回调函数。
        /// </summary>
        /// <param name="Msg">回调过程中的消息。</param>
        /// <param name="skt">与此过程相关的 Socket 对象。</param>
        private void LogInCallBack(P2PMessage Msg, Socket skt)
        {
            byte[] data;
            switch (Msg.MessageType)
            { 
                case P2PConstants.MSG_LOG_IN : // 登入消息发送完成后，接着发关用户信息。
                    ClientInfo ci = new ClientInfo(ClientName, string.Empty, 0);
                    byte[] cdata = ClientInfo.Serialization(ci);
                    Program.P2PClient.SendData(cdata, skt); // 发送客户端信息。
                    break;
                case P2PConstants.MSG_LOG_OK : // 登入成功。
                    _IsLogIn = true;
                    // 接下来获取服务端发来的已登入客户端例表。
                    data = Program.P2PClient.ReceiveKnownData(skt, sizeof(int)); // 接收长度。
                    int len = BitConverter.ToInt32(data, 0);
                    data = Program.P2PClient.ReceiveKnownData(skt, len);
                    ClientInfoCollections clst = ClientInfoCollections.Deserialization(data);
                    if (clst != null)
                        Program.LogInClients = clst;
                    Invoke(new MethodInvoker(delegate 
                    {
                        // 将服务器 IP 记录下来（以后维护登入状态要用到它）。
                        Program.SvrEndPoint = new IPEndPoint(IPAddress.Parse(txt_svrIP.Text.Trim()), int.Parse(txt_svrPort.Text.Trim()));
                        Program.Me = txt_Name.Text.Trim(); // 本次登入所使用的昵称。
                        this.Close();
                    }));
                    break;
                case P2PConstants.MSG_LOG_FAIL : // 登入失败。
                    _IsLogIn = false;
                    // 登入失败，下面接收原因。
                    data = Program.P2PClient.ReceiveKnownData(skt, sizeof(int)); // 先接收长度。
                    int dlen = BitConverter.ToInt32(data, 0);
                    data = Program.P2PClient.ReceiveKnownData(skt, dlen); // 在接收内容。
                    string err = Encoding.UTF8.GetString(data);
                    Invoke(new MethodInvoker(delegate 
                    {
                        MessageBox.Show(string.Format("登录失败：{0}", err), "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        lab_Tootip.Visible = false;
                    }));
                    break;

            }
            // Socket 对象使用完成后销毁它，否则连接的客户端一多众多的 socket 未释放将会占用巨大的资源。
            skt.Close();
            skt.Dispose();
        }

        private void LogIn(IPAddress IP, int Port)
        {
            P2PMessage msg = new P2PMessage();
            msg.MessageType = P2PConstants.MSG_LOG_IN;
            msg.ContentLength = P2PMessage.GetSize();
            Program.P2PClient.SendMessage(msg, new IPEndPoint(IP, Port), new AfterSendMessageHandler(LogInCallBack));
        }

        private void btn_logIn_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txt_Name.Text))
            {
                MessageBox.Show("必须要一个昵称。");
                txt_Name.Focus();
                return;
            }
            IPAddress IP = null;
            try
            {
                IP = IPAddress.Parse(txt_svrIP.Text);
            }
            catch
            {
                MessageBox.Show("服务端IP输入不正确！");
                txt_svrIP.Focus();
                return;
            }
            int Port = -1;
            try
            {
                Port = int.Parse(txt_svrPort.Text);
            }
            catch
            {
                MessageBox.Show("服务端端口不正确。");
                txt_svrPort.Focus();
                return;
            }

            lab_Tootip.Text = "正在登入，请稍候......";
            lab_Tootip.Visible = true;
            ClientName = txt_Name.Text.Trim();
            LogIn(IP, Port);
        }
    }
}
